<?php


/**
 * Description of AdminPresenter
 *
 * @author David Dusek
 */
use Nette\Application\UI\Form,
    CMS\User\Models\Group,
    CMS\User\Models\Resource,
    CMS\User\Models\Operation;

class GroupPresenter extends AdminPresenter
{    
    public function renderDefault() {
        $this->isAllowed("list", TRUE);
        $this->template->title = $this->getTitle("titleGroups", "list");
    }
    
    public function renderAdd() {
        $this->isAllowed("add", TRUE);
        $this->template->title = $this->getTitle("titleGroups", "add");                
    }
    
    public function renderEdit() {
        $this->isAllowed("edit", TRUE);
        $this->template->title = $this->getTitle("titleGroups", "edit");
    }
    
    public function renderRights($id) {
        $this->isAllowed("edit", TRUE);
        
        $this->template->title = $this->getTitle("titleGroups", "rights");
        $this->template->data = array();
        $this->template->groupId = $id;
        
        $resources = $this->em->getRepository('\CMS\User\Models\Resource')->findAll();
        $group = $this->em->getRepository('\CMS\User\Models\Group')->find($id);
        
        if ($group !== NULL) {
            $this->template->title .= " (" . $group->name . ")";
            if (is_array($resources)) {
                $data = $this->prepareRights($resources, $group);
                $this->template->data = $data;
            }
        } else {
            $this->flashMessage($this->translate("editGroupWrongId"));
            $this->redirect(":User:Group:default");
        }
    }
    
    public function handleAllowModule($id, $moduleName) {
        $this->isAllowed("edit", TRUE);
        
        $resources = $this->em->getRepository("\CMS\User\Models\Resource")->findByModule($moduleName);
        foreach ($resources as $resource) {
            $this->manageResource($id, $resource->id);
        }        
        $this->em->flush();
        
        $this->invalidateControl("rights");
    }
    
    public function handleDenyModule($id, $moduleName) {
        $this->isAllowed("edit", TRUE);
        
        $resources = $this->em->getRepository("\CMS\User\Models\Resource")->findByModule($moduleName);
        foreach ($resources as $resource) {
            $this->manageResource($id, $resource->id, TRUE);
        }
        $this->em->flush();
        
        $this->invalidateControl("rights");
    }
    
    public function handleAllowResource($id, $resId) {        
        $this->isAllowed("edit", TRUE);
        
        $this->manageResource($id, $resId);
        $this->em->flush();
        
        $this->invalidateControl("rights");
    }
    
    public function handleDenyResource($id, $resId) {        
        $this->isAllowed("edit", TRUE);
        
        $this->manageResource($id, $resId, TRUE);
        $this->em->flush();
        
        $this->invalidateControl("rights");
    }
    
    /**
     * Hromadna sprava skupin pro zdroj.
     * @param int $groupId Id skupiny.
     * @param int $resId Id zdroje.
     * @param boolean $deny Pokud je TRUE, tak vsechny operace pro skupinu
     * zakaze pokud je FALSE (default), tak vsechny operace pro skupinu povoli
     */
    private function manageResource($groupId, $resId, $deny = FALSE) {
        $group = $this->em->getRepository("\CMS\User\Models\Group")->find($groupId);
        $resource = $this->em->getRepository("\CMS\User\Models\Resource")->find($resId);
        if ($group !== NULL && $resource !== NULL) {
            $opIt = $resource->getOperations()->getIterator();
            
            while ($opIt->valid()) {                
                if ($group->getOperations()->contains($opIt->current()) && $deny) {
                    $group->removeOperation($opIt->current());
                } else if (!$group->getOperations()->contains($opIt->current()) && !$deny) {
                    $group->addOperation($opIt->current());
                }
                $opIt->next();
            }
        }
    }
    
    public function handleAllowOperation($id, $opId) {
        $this->isAllowed("edit", TRUE);
        
        $group = $this->em->getRepository("\CMS\User\Models\Group")->find($id);
        $operation = $this->em->getRepository("\CMS\User\Models\Operation")->find($opId);
        if ($group !== NULL && $operation !== NULL) {
            $group->addOperation($operation);
            $this->em->flush();
        }
        
        $this->invalidateControl("rights");        
    }
    
    public function handleDenyOperation($id, $opId) {
        $this->isAllowed("edit", TRUE);
        
        $group = $this->em->getRepository("\CMS\User\Models\Group")->find($id);
        $operation = $this->em->getRepository("\CMS\User\Models\Operation")->find($opId);
        if ($group !== NULL && $operation !== NULL) {
            $group->removeOperation($operation);
            $this->em->flush();
        }
        
        $this->invalidateControl("rights");
    }
    
    private function prepareRights($resources, Group $group) {
        $data = array();
        
        foreach ($resources as $resource) {
            $data[$resource->module][$resource->id]["title"] = $resource->title;
            $data[$resource->module][$resource->id]["operations"] = 
                    $this->prepareOperations($resource, $group);
        }
        
        return $data;
    }
    
    private function prepareOperations(Resource $resource, Group $group) {
        $allowedOps = $group->getOperations();
        
        $data = array();        
        
        $operationsIt = $resource->getOperations()->getIterator();
        while ($operationsIt->valid()) {
            $operation = $operationsIt->current();
            $data[$operation->id]["title"] = $operation->title;
            $data[$operation->id]["allowed"] = $allowedOps->contains($operation);
            $operationsIt->next();
        }
        
        return $data;
    }
    
    /**
     * Komponenta pro vykresleni tabulky s daty. 
     */
    protected function createComponentGrid() {
        $grid = new Gridito\Grid($this, 'grid');
       
        $qb = $this->em->getRepository('\CMS\User\Models\Group')->createQueryBuilder('g');
        $em = $this->em;
         
        $grid->setModel(new CMS\DoctrineQueryBuilderModel($qb));
        $grid->addColumn('id', 'Id')->setSortable(true);
        $grid->addColumn('name', $this->translate('name'))->setSortable(true);
        $grid->addColumn('usersCount', $this->translate('usersCount'))->setSortable(true);
        
        $presenter = $this;
        
        if ($this->isAllowed("edit")) {
            $grid->addButton('rightsButton', $this->translate('edit'), array(
                            'icon' => 'ui-icon-pencil',
                            'handler' => function ($group) use ($presenter) {
                                $presenter->redirect(':User:Group:edit', array("id" => $group->id));
                            },
                    ))
                    ->setShowText(false);        
                        
            $grid->addButton('editButton', $this->translate('rights'), array(
                            'icon' => 'ui-icon-key',
                            'handler' => function ($group) use ($presenter) {
                                $presenter->redirect(':User:Group:rights', array("id" => $group->id));
                            },
                    ))
                    ->setShowText(false);
        }
           
        if ($this->isAllowed("delete")) {
            $errNotEmpty = $this->translate("groupNotEmpty");
            $deleteSucc = $this->translate("groupDeleteSucc");
            $grid->addButton('deleteButton', $this->translate('delete'), array(
                            'icon' => 'ui-icon-trash',
                            'handler' => function ($group) use ($grid, $errNotEmpty, $deleteSucc, $em) {
                                if (count($group->getUsers()) > 0) {
                                    $grid->flashMessage(vsprintf($errNotEmpty, $group->getName()));
                                } else {
                                    $em->remove($group);
                                    $em->flush();
                                    $grid->flashMessage(vsprintf($deleteSucc, $group->getName()));
                                }

                            },
                    ))
                    ->setConfirmationQuestion($this->translate('deleteConfirnQuestionGroup'))
                    ->setShowText(false)
                    ->setAjax(true);
        }
    }
    
    /**
     * Vytvoreni formulare pro pridani a editaci informaci o skupine.
     * @return \Nette\Application\UI\Form 
     */
    protected function createComponentGroupForm() {
        $form = new Form();        
        
        $form->addText("name", $this->translate("name"))
                ->setRequired($this->translate('requiredErr'))
                ->addRule(Form::MAX_LENGTH, $this->translate("maxLenErr"), 45);        
        
        if ($this->getAction() == "edit") {
            $form->addHidden("id");
        }
               
        if ($this->getAction() == "add") {
            $form->addSubmit('add', $this->translate("add"));
        } else {
            $form->addSubmit('edit', $this->translate("edit"));
        }
        $form->onSuccess[] = callback($this, 'groupFormSubmitted');
        
        // pokud byl formular odeslan ale obsahoval chybu tak ho inicializujeme                
        if ($this->getAction() == "edit") {
            $id = intval($this->getParameter("id"));
            
            if ($id > 0) {
                $groupRep = $this->em->getRepository("\CMS\User\Models\Group");
                $group = $groupRep->find($id);
                if ($group === null) {
                    $this->flashMessage($this->translate("editGroupWrongId"));
                    $this->redirect(":User:Group:default");
                }

                $form->setDefaults(array(
                    "id" => $group->id,
                    "name" => $group->name                    
                ));
            }
        }
        
        return $form;
    }
    
    /**
     * Zpracovani dat z formulare pro pridani a editaci uzivatelske skupiny.
     * @param Form $form 
     */
    public function groupFormSubmitted(Form $form) {
        $values = $form->getValues();
        $groupRep = $this->em->getRepository("\CMS\User\Models\Group");
        
        if ($this->getAction() == "add") {
            $group = new Group();
        } else {
            $group = $groupRep->find($values["id"]);
            
            if ($group === null) {
                $this->flashMessage($this->translate("editWrongId"));
                $this->redirect(":User:Group:default");
            }
        }
        
        $group->setName($values["name"]);                
        
        if ($this->getAction() == "add") {
            $this->em->persist($group);
            $this->flashMessage($this->translate("addGroupSucceeded"));
        } else {
            $this->flashMessage($this->translate("editGroupSucceeded"));
        }
        $this->em->flush();

        $this->redirect(":User:Group:edit", array("id" => $group->id));        
    }
    
    /**
     * Formular pro spravu uzivatelu ve skupine.
     * @return \Nette\Application\UI\Form 
     */
    protected function createComponentUserGroupForm() {
        $form = new Form();
        $groupRep = $this->em->getRepository("\CMS\User\Models\Group");
        $userRep = $this->em->getRepository("\CMS\User\Models\User");
        $usersIn = array();
        $usersFree = array();
        
        $id = intval($this->getParameter("id"));
        if ($id == 0) {
            $id = intval($this->getParameter("groupId"));
        }
        

        if ($id > 0) {        
            $group = $groupRep->find($id);
            if ($group === null) {
                $this->flashMessage($this->translate("editGroupWrongId"));
                $this->redirect(":User:Group:default");
            }
                        
            $usersForIn = $group->getUsers();
            $iterator = $usersForIn->getIterator();
            while ($iterator->valid()) {
                $userForIn = $iterator->current();
                $usersIn[$userForIn->getId()] = $userForIn->getName() . " " . $userForIn->getSurname();
                $iterator->next();
            }
            
            $usersForFree = $userRep->usersNotInGroup($group->getId());        
            if (is_array($usersForFree)) {
                foreach ($usersForFree as $userForFree) {
                    $usersFree[$userForFree->getId()] = $userForFree->getName() . " " . $userForFree->getSurname();
                }
            }   
            
        }
           
        $form->addHidden("groupId")->setDefaultValue($id);
        $form->getElementPrototype()->class("ajax");
        $form->addMultiSelect("usersIn", $this->translate("usersInGroup"), $usersIn, 20);
        $form->addMultiSelect("usersFree", $this->translate("usersForAddToGroup"), $usersFree, 20);
        $form->addSubmit("add", "<<")->onClick[] = array($this, "addUser");
        return $form;
    }
    
    /**
     * Pridani uzivatelu do skupiny
     * @param Nette\Forms\Controls\SubmitButton $button 
     */
    public function addUser(Nette\Forms\Controls\SubmitButton $button) {
        $values = $button->form->getValues();        
        $userToAdd = $values["usersFree"];
        if (count($userToAdd)) {
            $group = $this->em->getRepository("\CMS\User\Models\Group")->find($values["groupId"]);
            $userRep = $this->em->getRepository("\CMS\User\Models\User");
            
            foreach ($userToAdd as $addUser) {                
                $group->addUser($userRep->find($addUser));
            }
            
            $this->em->flush();
            
            // nove hodnoty pro selecty
            $usersIn = array();
            $usersFree = array();
            $usersForIn = $group->getUsers();
            $iterator = $usersForIn->getIterator();
            while ($iterator->valid()) {
                $userForIn = $iterator->current();
                $usersIn[$userForIn->getId()] = $userForIn->getName() . " " . $userForIn->getSurname();
                $iterator->next();
            }
            
            $usersForFree = $userRep->usersNotInGroup($group->getId());        
            if (is_array($usersForFree)) {
                foreach ($usersForFree as $userForFree) {
                    $usersFree[$userForFree->getId()] = $userForFree->getName() . " " . $userForFree->getSurname();
                }
            }   
            
            $form = $this->getComponent("userGroupForm");
            $form->getComponent("usersIn")->setItems($usersIn);
            $form->getComponent("usersFree")->setItems($usersFree);
            
            if ($this->presenter->isAjax()) {
                $this->invalidateControl();
            }
        }
    }
}
